﻿//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
* 类 名 称 ：Timer
* 类 描 述 ：
* 作    者 ：henrychang
* 创建时间 ：2019/1/19 17:08:49
*******************************************************************
* Copyright @ henrychang 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using System;
using UnityEngine;

namespace TouchFish.Timer
{
    [Serializable]
    public class Timer
    {
        internal Action<float> UpdateEvent;
        internal Action EndEvent;

        /// <summary>
        /// 用户指定的定时器标志，便于手动清除、暂停、恢复
        /// </summary>
        [SerializeField]
        internal string _flag;

        /// <summary>
        /// 用户设定的定时时长
        /// </summary>
        [SerializeField]
        private float _time = -1;

        /// <summary>
        /// 是否循环执行
        /// </summary>
        [SerializeField]
        private bool _loop;

        /// <summary>
        /// 是否忽略Timescale
        /// </summary>
        [SerializeField]
        private bool _ignorTimescale;

        /// <summary>
        /// 获得当前时间
        /// </summary>
        private float CurrentTime { get { return _ignorTimescale ? UnityEngine.Time.realtimeSinceStartup : UnityEngine.Time.time; } }

        /// <summary>
        /// 缓存时间
        /// </summary>
        [SerializeField]
        private float startTime;

        /// <summary>
        /// 已经流逝的时光
        /// </summary>
        [SerializeField]
        private float timePassed;

        /// <summary>
        /// 计时器是否结束
        /// </summary>
        [SerializeField]
        private bool _isFinish = false;

        /// <summary>
        /// 计时器是否暂停
        /// </summary>
        [SerializeField]
        private bool _isPause = false;

        private static bool showLog = true;

        /// <summary>
        /// 当前定时器设定的时间
        /// </summary>
        public float Duration { get { return _time; } }

        /// <summary>
        /// 暂停计时器
        /// </summary>
        public bool IsPause
        {
            get { return _isPause; }
            set
            {
                if (value)
                {
                    Pause();
                }
                else
                {
                    Resum();
                }
            }
        }

        /// <summary>
        /// 构造定时器
        /// </summary>
        /// <param name="time">定时时长</param>
        /// <param name="flag">定时器标识符</param>
        /// <param name="loop">是否循环</param>
        /// <param name="ignorTimescale">是否忽略TimeScale</param>
        internal Timer(float time, string flag, bool loop = false, bool ignorTimescale = true)
        {
            _time = time;
            _loop = loop;
            _ignorTimescale = ignorTimescale;
            startTime = CurrentTime;
            if (TimerDriver.Instance.Timers.Exists((v) => { return v._flag == flag; }))
            {
                if (showLog) Debug.LogWarningFormat("【TimerTrigger（容错）】:存在相同的标识符【{0}】！", flag);
            }
            _flag = string.IsNullOrEmpty(flag) ? GetHashCode().ToString() : flag;//设置辨识标志符
        }

        /// <summary>
        /// 暂停计时
        /// </summary>
        internal void Pause()
        {
            if (_isFinish)
            {
                if (showLog) Debug.LogWarning("【TimerTrigger（容错）】:计时已经结束！");
            }
            else
            {
                _isPause = true;
            }
        }

        /// <summary>
        /// 继续计时
        /// </summary>
        internal void Resum()
        {
            if (_isFinish)
            {
                if (showLog) Debug.LogWarning("【TimerTrigger（容错）】:计时已经结束！");
            }
            else
            {
                if (_isPause)
                {
                    startTime = CurrentTime - timePassed;
                    _isPause = false;
                }
                else
                {
                    if (showLog) Debug.LogWarning("【TimerTrigger（容错）】:计时并未处于暂停状态！");
                }
            }
        }

        /// <summary>
        /// 刷新定时器
        /// </summary>
        internal void Update()
        {
            if (!_isFinish && !_isPause) //运行中
            {
                timePassed = CurrentTime - startTime;
                if (null != UpdateEvent) UpdateEvent.Invoke(Mathf.Clamp01(timePassed / _time));
                if (timePassed >= _time)
                {
                    if (null != EndEvent) EndEvent.Invoke();
                    if (_loop)
                    {
                        startTime = CurrentTime;
                    }
                    else
                    {
                        Stop();
                    }
                }
            }
        }

        /// <summary>
        /// 回收定时器
        /// </summary>
        internal void Stop()
        {
            if (TimerDriver.Instance.Timers.Contains(this))
            {
                TimerDriver.Instance.Timers.Remove(this);
            }
            _time = -1;
            UpdateEvent = null;
            EndEvent = null;
            _isFinish = true;
            _isPause = false;
        }

        #region-------------AddEvent-------------------

        public void AddEvent(Action completedEvent)
        {
            if (null == EndEvent)
            {
                EndEvent = completedEvent;
            }
            else
            {
                Delegate[] delegates = EndEvent.GetInvocationList();
                if (!Array.Exists(delegates, (v) => { return v == (Delegate)completedEvent; }))
                {
                    EndEvent += completedEvent;
                }
            }
        }

        public void AddEvent(Action<float> updateEvent)
        {
            if (null == UpdateEvent)
            {
                UpdateEvent = updateEvent;
            }
            else
            {
                Delegate[] delegates = UpdateEvent.GetInvocationList();

                if (!Array.Exists(delegates, (v) => { return v == (Delegate)updateEvent; }))
                {
                    UpdateEvent += updateEvent;
                }
            }
        }

        #endregion
        #region ---------------运行中的定时器参数修改-----------

        /// <summary>
        /// 重新设置运行中的定时器的时间
        /// </summary>
        /// <param name="endTime">定时时长</param>
        public Timer SetTime(float endTime)
        {
            if (_isFinish)
            {
                if (showLog) Debug.LogWarning("【TimerTrigger（容错）】:计时已经结束！");
            }
            else
            {
                if (endTime == _time)
                {
                    if (showLog) Debug.Log("【TimerTrigger（容错）】:时间已被设置，请勿重复操作！");
                }
                else
                {
                    if (endTime < 0)
                    {
                        if (showLog) Debug.Log("【TimerTrigger（容错）】:时间不支持负数，已自动取正！");
                        endTime = Mathf.Abs(endTime);
                    }
                    if (endTime < timePassed)//如果用户设置时间已错失
                    {
                        if (showLog) Debug.Log(string.Format("【TimerTrigger（容错）】:时间设置过短【passed:set=>{0}:{1}】,事件提前触发！", timePassed, endTime));
                    }
                    _time = endTime;
                }
            }
            return this;
        }

        /// <summary>
        /// 设置运行中的定时器的loop状态
        /// </summary>
        /// <param name="loop"></param>
        public Timer Setloop(bool loop)
        {
            if (!_isFinish)
            {
                _loop = loop;
            }
            else
            {
                if (showLog) Debug.Log("【TimerTrigger（容错）】:定时器已失效,设置Loop Fail！");
            }
            return this;
        }

        /// <summary>
        /// 设置运行中的定时器的ignoreTimescale状态
        /// </summary>
        /// <param name="loop"></param>
        public Timer SetIgnoreTimeScale(bool ignoreTimescale)
        {
            if (!_isFinish)
            {
                _ignorTimescale = ignoreTimescale;
            }
            else
            {
                if (showLog) Debug.Log("【TimerTrigger（容错）】:定时器已失效，设置IgnoreTimescale Fail！");
            }
            return this;
        }

        #endregion
    }
}